Description: [PATCH 2/3] arpspoof: allow use of multiple targets. Last hunk modified by João Salavisa <joao.salavisa@gmail.com>
in order to fix a bug with "-t" option of arpspoof. See https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=706766 fo more information.
Author: Stefan Tomanek <stefan@pico.ruhr.de>
 ---
This patch header follows DEP-3: http://dep.debian.net/deps/dep3/


--- a/arpspoof.8
+++ b/arpspoof.8
@@ -25,7 +25,7 @@
 Specify the interface to use.
 .IP "\fB-t \fItarget\fR"
 Specify a particular host to ARP poison (if not specified, all hosts
-on the LAN).
+on the LAN). Repeat to specify multiple hosts.
 .IP "\fB\-r\fR"
 Poison both hosts (host and target) to capture traffic in both directions.
 (only valid in conjuntion with \-t)
--- a/arpspoof.c
+++ b/arpspoof.c
@@ -29,9 +29,14 @@
 
 extern char *ether_ntoa(struct ether_addr *);
 
+struct host {
+	in_addr_t ip;
+	struct ether_addr mac;
+};
+
 static libnet_t *l;
-static struct ether_addr spoof_mac, target_mac;
-static in_addr_t spoof_ip, target_ip;
+static struct host spoof = {0};
+static struct host *targets;
 static char *intf;
 static int poison_reverse;
 
@@ -133,30 +138,46 @@
 	return (0);
 }
 
+static int arp_find_all() {
+	struct host *target = targets;
+	while(target->ip) {
+		if (arp_find(target->ip, &target->mac)) {
+			return 1;
+		}
+		target++;
+	}
+
+	return 0;
+}
+
 static void
 cleanup(int sig)
 {
-	int fw = arp_find(spoof_ip, &spoof_mac);
-	int bw = poison_reverse && target_ip && arp_find(target_ip, &target_mac);
+	int fw = arp_find(spoof.ip, &spoof.mac);
+	int bw = poison_reverse && targets[0].ip && arp_find_all();
 	int i;
 
 	fprintf(stderr, "Cleaning up and re-arping targets...\n");
 	for (i = 0; i < 5; i++) {
-		/* XXX - on BSD, requires ETHERSPOOF kernel. */
-		if (fw) {
-			arp_send(l, ARPOP_REPLY,
-				 (u_int8_t *)&spoof_mac, spoof_ip,
-				 (target_ip ? (u_int8_t *)&target_mac : NULL),
-				 target_ip);
-			/* we have to wait a moment before sending the next packet */
-			sleep(1);
-		}
-		if (bw) {
-			arp_send(l, ARPOP_REPLY,
-				 (u_int8_t *)&target_mac, target_ip,
-				 (u_int8_t *)&spoof_mac,
-				 spoof_ip);
-			sleep(1);
+		struct host *target = targets;
+		while(target->ip) {
+			/* XXX - on BSD, requires ETHERSPOOF kernel. */
+			if (fw) {
+				arp_send(l, ARPOP_REPLY,
+					 (u_int8_t *)&spoof.mac, spoof.ip,
+					 (target->ip ? (u_int8_t *)&target->mac : NULL),
+					 target->ip);
+				/* we have to wait a moment before sending the next packet */
+				sleep(1);
+			}
+			if (bw) {
+				arp_send(l, ARPOP_REPLY,
+					 (u_int8_t *)&target->mac, target->ip,
+					 (u_int8_t *)&spoof.mac,
+					 spoof.ip);
+				sleep(1);
+			}
+			target++;
 		}
 	}
 
@@ -171,10 +192,15 @@
 	char pcap_ebuf[PCAP_ERRBUF_SIZE];
 	char libnet_ebuf[LIBNET_ERRBUF_SIZE];
 	int c;
+	int n_targets;
 
+	spoof.ip = 0;
 	intf = NULL;
-	spoof_ip = target_ip = 0;
 	poison_reverse = 0;
+	n_targets = 0;
+
+	/* allocate enough memory for target list */
+	targets = calloc( argc+1, sizeof(struct host) );
 
 	while ((c = getopt(argc, argv, "ri:t:h?V")) != -1) {
 		switch (c) {
@@ -182,7 +208,7 @@
 			intf = optarg;
 			break;
 		case 't':
-			if ((target_ip = libnet_name2addr4(l, optarg, LIBNET_RESOLVE)) == -1)
+			if ((targets[n_targets++].ip = libnet_name2addr4(l, optarg, LIBNET_RESOLVE)) == -1)
 				usage();
 			break;
 		case 'r':
@@ -198,12 +224,12 @@
 	if (argc != 1)
 		usage();
 
-	if (poison_reverse && !target_ip) {
+	if (poison_reverse && !n_targets) {
 		errx(1, "Spoofing the reverse path (-r) is only available when specifying a target (-t).");
 		usage();
 	}
 
-	if ((spoof_ip = libnet_name2addr4(l, argv[0], LIBNET_RESOLVE)) == -1)
+	if ((spoof.ip = libnet_name2addr4(l, argv[0], LIBNET_RESOLVE)) == -1)
 		usage();
 	
 	if (intf == NULL && (intf = pcap_lookupdev(pcap_ebuf)) == NULL)
@@ -211,15 +237,19 @@
 	
 	if ((l = libnet_init(LIBNET_LINK, intf, libnet_ebuf)) == NULL)
 		errx(1, "%s", libnet_ebuf);
-	
-	if (target_ip != 0 && !arp_find(target_ip, &target_mac))
-		errx(1, "couldn't arp for host %s",
-		     libnet_addr2name4(target_ip, LIBNET_DONT_RESOLVE));
+
+	struct host *target = targets;
+	while(target->ip) {
+		if (target->ip != 0 && !arp_find(target->ip, &target->mac))
+			errx(1, "couldn't arp for host %s",
+			libnet_addr2name4(target->ip, LIBNET_DONT_RESOLVE));
+		target++;
+	}
 
 	if (poison_reverse) {
-		if (!arp_find(spoof_ip, &spoof_mac)) {
+		if (!arp_find(spoof.ip, &spoof.mac)) {
 			errx(1, "couldn't arp for spoof host %s",
-			     libnet_addr2name4(spoof_ip, LIBNET_DONT_RESOLVE));
+			     libnet_addr2name4(spoof.ip, LIBNET_DONT_RESOLVE));
 		}
 	}
 
@@ -228,12 +258,20 @@
 	signal(SIGTERM, cleanup);
 
 	for (;;) {
-		arp_send(l, ARPOP_REPLY, NULL, spoof_ip,
-			 (target_ip ? (u_int8_t *)&target_mac : NULL),
-			 target_ip);
-		if (poison_reverse) {
-			arp_send(l, ARPOP_REPLY, NULL, target_ip, (uint8_t *)&spoof_mac, spoof_ip);
+    if (!n_targets) {
+      arp_send(l, ARPOP_REPLY, my_ha, spoof.ip, brd_ha, 0, my_ha);
+    } else {
+		struct host *target = targets;
+		while(target->ip) {
+			arp_send(l, ARPOP_REPLY, NULL, spoof.ip,
+				(target->ip ? (u_int8_t *)&target->mac : NULL),
+				target->ip);
+			if (poison_reverse) {
+				arp_send(l, ARPOP_REPLY, NULL, target->ip, (uint8_t *)&spoof.mac, spoof.ip);
+			}
+			target++;
 		}
+    }
 
 		sleep(2);
 	}
